// Interfaces (接口) 示例
// 演示 Pascal 中接口的各种用法
program p_32_interfaces;

{$mode objfpc}{$H+}
// {$mode objfpc} 启用 Object Pascal 模式，支持面向对象编程
// {$H+} 启用长字符串支持（AnsiString）

// 引入单元文件
uses
  SysUtils;  // 系统工具单元，包含常用的系统函数

// 定义接口：可播放媒体
type
  IMediaPlayer = interface
    ['{12345678-1234-1234-1234-123456789012}']
    procedure Play;
    procedure Stop;
    procedure Pause;
    function GetDuration: Integer;
    property Duration: Integer read GetDuration;
  end;

// 定义接口：可录制媒体
type
  IMediaRecorder = interface
    ['{12345678-1234-1234-1234-123456789013}']
    procedure Record;
    procedure StopRecording;
    function GetRecordingQuality: String;
  end;

// 定义接口：可显示信息
type
  IDisplayable = interface
    ['{12345678-1234-1234-1234-123456789014}']
    procedure DisplayInfo;
  end;

// 定义接口：可充电设备（继承自IDisplayable）
type
  IChargeable = interface(IDisplayable)
    ['{12345678-1234-1234-1234-123456789015}']
    procedure Charge;
    function GetBatteryLevel: Integer;
    property BatteryLevel: Integer read GetBatteryLevel;
  end;

// 定义实现类：音乐播放器
type
  TMusicPlayer = class(TInterfacedObject, IMediaPlayer)
  private
    FTitle: String;
    FDuration: Integer;
    FIsPlaying: Boolean;
  public
    constructor Create(const ATitle: String; ADuration: Integer);
    
    // 实现 IMediaPlayer 接口
    procedure Play;
    procedure Stop;
    procedure Pause;
    function GetDuration: Integer;
    
    property Title: String read FTitle;
    property IsPlaying: Boolean read FIsPlaying;
  end;

// TMusicPlayer类的实现
constructor TMusicPlayer.Create(const ATitle: String; ADuration: Integer);
begin
  inherited Create;
  FTitle := ATitle;
  FDuration := ADuration;
  FIsPlaying := False;
  WriteLn('  创建音乐播放器: ', FTitle);
end;

procedure TMusicPlayer.Play;
begin
  if not FIsPlaying then
  begin
    FIsPlaying := True;
    WriteLn('  音乐播放器开始播放: ', FTitle);
  end
  else
    WriteLn('  音乐播放器已在播放状态');
end;

procedure TMusicPlayer.Stop;
begin
  if FIsPlaying then
  begin
    FIsPlaying := False;
    WriteLn('  音乐播放器停止播放: ', FTitle);
  end
  else
    WriteLn('  音乐播放器未在播放');
end;

procedure TMusicPlayer.Pause;
begin
  if FIsPlaying then
  begin
    FIsPlaying := False;
    WriteLn('  音乐播放器暂停播放: ', FTitle);
  end
  else
    WriteLn('  音乐播放器未在播放，无法暂停');
end;

function TMusicPlayer.GetDuration: Integer;
begin
  Result := FDuration;
end;

// 定义实现类：视频播放器（实现多个接口）
type
  TVideoPlayer = class(TInterfacedObject, IMediaPlayer, IMediaRecorder)
  private
    FTitle: String;
    FDuration: Integer;
    FIsPlaying: Boolean;
    FIsRecording: Boolean;
    FRecordingQuality: String;
  public
    constructor Create(const ATitle: String; ADuration: Integer; const ARecordingQuality: String);
    
    // 实现 IMediaPlayer 接口
    procedure Play;
    procedure Stop;
    procedure Pause;
    function GetDuration: Integer;
    
    // 实现 IMediaRecorder 接口
    procedure Record;
    procedure StopRecording;
    function GetRecordingQuality: String;
    
    property Title: String read FTitle;
    property IsPlaying: Boolean read FIsPlaying;
    property IsRecording: Boolean read FIsRecording;
  end;

// TVideoPlayer类的实现
constructor TVideoPlayer.Create(const ATitle: String; ADuration: Integer; const ARecordingQuality: String);
begin
  inherited Create;
  FTitle := ATitle;
  FDuration := ADuration;
  FRecordingQuality := ARecordingQuality;
  FIsPlaying := False;
  FIsRecording := False;
  WriteLn('  创建视频播放器: ', FTitle, ' (录制质量: ', FRecordingQuality, ')');
end;

procedure TVideoPlayer.Play;
begin
  if not FIsPlaying then
  begin
    FIsPlaying := True;
    WriteLn('  视频播放器开始播放: ', FTitle);
  end
  else
    WriteLn('  视频播放器已在播放状态');
end;

procedure TVideoPlayer.Stop;
begin
  if FIsPlaying then
  begin
    FIsPlaying := False;
    WriteLn('  视频播放器停止播放: ', FTitle);
  end
  else
    WriteLn('  视频播放器未在播放');
end;

procedure TVideoPlayer.Pause;
begin
  if FIsPlaying then
  begin
    FIsPlaying := False;
    WriteLn('  视频播放器暂停播放: ', FTitle);
  end
  else
    WriteLn('  视频播放器未在播放，无法暂停');
end;

function TVideoPlayer.GetDuration: Integer;
begin
  Result := FDuration;
end;

procedure TVideoPlayer.Record;
begin
  if not FIsRecording then
  begin
    FIsRecording := True;
    WriteLn('  视频播放器开始录制: ', FTitle, ' (质量: ', FRecordingQuality, ')');
  end
  else
    WriteLn('  视频播放器已在录制状态');
end;

procedure TVideoPlayer.StopRecording;
begin
  if FIsRecording then
  begin
    FIsRecording := False;
    WriteLn('  视频播放器停止录制: ', FTitle);
  end
  else
    WriteLn('  视频播放器未在录制');
end;

function TVideoPlayer.GetRecordingQuality: String;
begin
  Result := FRecordingQuality;
end;

// 定义实现类：智能手机（实现多个接口）
type
  TSmartPhone = class(TInterfacedObject, IMediaPlayer, IMediaRecorder, IChargeable)
  private
    FModel: String;
    FDuration: Integer;
    FIsPlaying: Boolean;
    FIsRecording: Boolean;
    FRecordingQuality: String;
    FBatteryLevel: Integer;
  public
    constructor Create(const AModel: String; ADuration: Integer; const ARecordingQuality: String);
    
    // 实现 IMediaPlayer 接口
    procedure Play;
    procedure Stop;
    procedure Pause;
    function GetDuration: Integer;
    
    // 实现 IMediaRecorder 接口
    procedure Record;
    procedure StopRecording;
    function GetRecordingQuality: String;
    
    // 实现 IChargeable 接口
    procedure Charge;
    procedure DisplayInfo;
    function GetBatteryLevel: Integer;
    
    property Model: String read FModel;
    property IsPlaying: Boolean read FIsPlaying;
    property IsRecording: Boolean read FIsRecording;
    property BatteryLevel: Integer read FBatteryLevel;
  end;

// TSmartPhone类的实现
constructor TSmartPhone.Create(const AModel: String; ADuration: Integer; const ARecordingQuality: String);
begin
  inherited Create;
  FModel := AModel;
  FDuration := ADuration;
  FRecordingQuality := ARecordingQuality;
  FIsPlaying := False;
  FIsRecording := False;
  FBatteryLevel := 100;  // 初始电量100%
  WriteLn('  创建智能手机: ', FModel, ' (录制质量: ', FRecordingQuality, ')');
end;

procedure TSmartPhone.Play;
begin
  if not FIsPlaying then
  begin
    FIsPlaying := True;
    WriteLn('  智能手机 ', FModel, ' 开始播放媒体');
  end
  else
    WriteLn('  智能手机 ', FModel, ' 已在播放状态');
end;

procedure TSmartPhone.Stop;
begin
  if FIsPlaying then
  begin
    FIsPlaying := False;
    WriteLn('  智能手机 ', FModel, ' 停止播放媒体');
  end
  else
    WriteLn('  智能手机 ', FModel, ' 未在播放');
end;

procedure TSmartPhone.Pause;
begin
  if FIsPlaying then
  begin
    FIsPlaying := False;
    WriteLn('  智能手机 ', FModel, ' 暂停播放媒体');
  end
  else
    WriteLn('  智能手机 ', FModel, ' 未在播放，无法暂停');
end;

function TSmartPhone.GetDuration: Integer;
begin
  Result := FDuration;
end;

procedure TSmartPhone.Record;
begin
  if not FIsRecording then
  begin
    FIsRecording := True;
    WriteLn('  智能手机 ', FModel, ' 开始录制 (质量: ', FRecordingQuality, ')');
  end
  else
    WriteLn('  智能手机 ', FModel, ' 已在录制状态');
end;

procedure TSmartPhone.StopRecording;
begin
  if FIsRecording then
  begin
    FIsRecording := False;
    WriteLn('  智能手机 ', FModel, ' 停止录制');
  end
  else
    WriteLn('  智能手机 ', FModel, ' 未在录制');
end;

function TSmartPhone.GetRecordingQuality: String;
begin
  Result := FRecordingQuality;
end;

procedure TSmartPhone.Charge;
begin
  WriteLn('  智能手机 ', FModel, ' 正在充电...');
  FBatteryLevel := 100;
  WriteLn('  智能手机 ', FModel, ' 电量已充满');
end;

procedure TSmartPhone.DisplayInfo;
begin
  WriteLn('  智能手机型号: ', FModel);
  WriteLn('  电池电量: ', FBatteryLevel, '%');
  WriteLn('  录制质量: ', FRecordingQuality);
end;

function TSmartPhone.GetBatteryLevel: Integer;
begin
  Result := FBatteryLevel;
end;

// 程序主入口
begin
  WriteLn('=== Pascal 接口示例 ===');
  WriteLn;
  
  // 1. 创建实现接口的对象
  WriteLn('1. 创建实现接口的对象:');
  var musicPlayer: TMusicPlayer := TMusicPlayer.Create('经典音乐集', 3600);
  var videoPlayer: TVideoPlayer := TVideoPlayer.Create('高清视频', 7200, '1080p');
  var smartPhone: TSmartPhone := TSmartPhone.Create('SuperPhone X', 1800, '4K');
  
  try
    WriteLn;
    
    // 2. 通过接口变量使用对象
    WriteLn('2. 通过接口变量使用对象:');
    
    // 使用 IMediaPlayer 接口
    var mediaPlayer: IMediaPlayer;
    
    mediaPlayer := musicPlayer;
    WriteLn('  通过 IMediaPlayer 接口操作音乐播放器:');
    mediaPlayer.Play;
    WriteLn('    媒体时长: ', mediaPlayer.Duration, ' 秒');
    mediaPlayer.Pause;
    mediaPlayer.Stop;
    
    WriteLn;
    
    mediaPlayer := videoPlayer;
    WriteLn('  通过 IMediaPlayer 接口操作视频播放器:');
    mediaPlayer.Play;
    WriteLn('    媒体时长: ', mediaPlayer.Duration, ' 秒');
    mediaPlayer.Stop;
    
    WriteLn;
    
    // 使用 IMediaRecorder 接口
    var mediaRecorder: IMediaRecorder;
    
    mediaRecorder := videoPlayer;
    WriteLn('  通过 IMediaRecorder 接口操作视频播放器:');
    mediaRecorder.Record;
    WriteLn('    录制质量: ', mediaRecorder.GetRecordingQuality);
    mediaRecorder.StopRecording;
    
    WriteLn;
    
    mediaRecorder := smartPhone;
    WriteLn('  通过 IMediaRecorder 接口操作智能手机:');
    mediaRecorder.Record;
    WriteLn('    录制质量: ', mediaRecorder.GetRecordingQuality);
    mediaRecorder.StopRecording;
    
    WriteLn;
    
    // 3. 多接口演示
    WriteLn('3. 多接口演示:');
    var chargeable: IChargeable;
    
    chargeable := smartPhone;
    WriteLn('  通过 IChargeable 接口操作智能手机:');
    chargeable.DisplayInfo;
    chargeable.Charge;
    
    WriteLn;
    
    // 4. 接口多态性
    WriteLn('4. 接口多态性:');
    var mediaPlayers: array[1..3] of IMediaPlayer;
    
    mediaPlayers[1] := musicPlayer;
    mediaPlayers[2] := videoPlayer;
    mediaPlayers[3] := smartPhone;
    
    for var i := 1 to 3 do
    begin
      WriteLn('  操作媒体播放器 ', i, ':');
      mediaPlayers[i].Play;
      WriteLn('    时长: ', mediaPlayers[i].Duration, ' 秒');
      mediaPlayers[i].Stop;
      WriteLn;
    end;
    
    WriteLn;
    
    // 5. 接口类型检查
    WriteLn('5. 接口类型检查:');
    var obj: TObject;
    
    obj := smartPhone;
    if Supports(obj, IMediaPlayer) then
      WriteLn('  智能手机支持 IMediaPlayer 接口');
    
    if Supports(obj, IMediaRecorder) then
      WriteLn('  智能手机支持 IMediaRecorder 接口');
    
    if Supports(obj, IChargeable) then
      WriteLn('  智能手机支持 IChargeable 接口');
    
    WriteLn;
    
    // 6. 接口继承演示
    WriteLn('6. 接口继承演示:');
    // IChargeable 继承自 IDisplayable
    var displayable: IDisplayable;
    
    displayable := smartPhone;  // IChargeable 继承了 IDisplayable
    WriteLn('  通过 IDisplayable 接口操作智能手机:');
    displayable.DisplayInfo;
  finally
    // 释放对象
    musicPlayer.Free;
    videoPlayer.Free;
    smartPhone.Free;
  end;
  
  WriteLn;
  WriteLn('演示了 Pascal 中接口的各种用法');
  
  // 等待用户按键，防止程序窗口立即关闭
  ReadLn;
end.